package com.base.cn.platform.os.controller.user.login;

import com.base.cn.platform.os.common.constants.ConfigName;
import com.base.cn.platform.os.common.j2cache.CustomCacheChannel;
import com.base.cn.platform.os.common.j2cache.J2CacheRegion;
import com.base.cn.platform.os.common.md5.MD5;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.http.HttpUtil;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.common.utils.user.ProfileType;
import com.base.cn.platform.os.common.utils.user.UserExpandFrom;
import com.base.cn.platform.os.common.utils.web.AesCbcUtil;
import com.base.cn.platform.os.common.utils.web.thirdLogin.WXLoginUtils;
import com.base.cn.platform.os.controller.cmmon.ApiBaseController;
import com.base.cn.platform.os.service.manage.config.SysConfigService;
import com.base.cn.platform.os.service.manage.user.user.CuserProfileService;
import com.base.cn.platform.os.service.upload.FileUploadService;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;

/**
 * 微信小程序登录
 * @author s.li
 * @create 2018-09-08-11:30
 */
@RestController
@RequestMapping("/api/wxApplet/user")
public class WXApplyLoginController extends ApiBaseController {

    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private CuserProfileService cuserProfileService;
    @Autowired
    private FileUploadService fileUploadService;
    @Autowired
    private CustomCacheChannel customCacheChannel;

    /**
     * 微信小程获取微信用户数据
     * @param encryptedData
     * @param iv
     * @param code 小程序的code
     * @return Map<String,Object>
     */
    @PostMapping("/getWeiXin3rdSession")
    public Map<String,Object> getWeiXin3rdSession(@RequestParam(value = "encryptedData") String encryptedData,
                                                  @RequestParam(value = "iv") String iv,
                                                  @RequestParam("code") String code) throws Exception{
        logger.info("-----------------------request getWeiXin3rdSession");
        TreeMap<String,String> configMap = sysConfigService.getSysConfigContext(ConfigName.WEIXINAPP);
        logger.info("-----------------------configMap:"+configMap);
        //获取openid
        String result;
        try {
            result = HttpUtil.doGet("https://api.weixin.qq.com/sns/jscode2session?appid="+configMap.get("appId")+"&secret="+configMap.get("secret")+"&js_code="+code+"&grant_type=authorization_code");
            logger.info("=========================jscode2session result:"+result);
        }catch (IOException e){
            throw e;
        }
        //请求微信服务获取用户信息
        Map<String,String> resultMap = gson.fromJson(result,new TypeToken<Map<String,String>>(){}.getType());
        String errcode = resultMap.get("errcode");
        if(!StringUtils.isNotEmpty(errcode) && StringUtils.isNotEmpty(resultMap.get("openid"))){
            String openId = resultMap.get("openid");
            String sessionKey = resultMap.get("session_key");
            //解密unionid(通过aes解密方式)
            result = AesCbcUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8");
            logger.info("-------------------------aes cbc result:"+result);
            Map<String,Object> _result = gson.fromJson(result,new TypeToken<Map<String,Object>>(){}.getType());
            if(ObjectUtils.isNotEmpty(_result) && StringUtils.isNotEmpty(_result.get("unionId"))){
                //得到微信唯一的标识
                String unionId = (String)_result.get("unionId");
                logger.info("-------------------------unionId:"+unionId);
                String avatarUrl = (String)_result.get("avatarUrl");
                String nickName = (String)_result.get("nickName");
                Map<String,Object> profile = new HashMap<>();
                profile.put("value",unionId);
                profile.put("profileType", ProfileType.WEIXIN.toString());
                profile.put("avatar",avatarUrl);
                profile.put("name",nickName);
                profile.put("openId",openId);
                Map<String,Object> _resultMap = cuserProfileService.saveUserProfile(profile, UserExpandFrom.appletThirdWeiXin.getKey());
                String status = (String)_resultMap.get("status");
                if(StringUtils.isEmpty(status)){
                    String rd3Session = MD5.getMD5(openId+sessionKey+unionId+StringUtils.getRandomString(32)+System.currentTimeMillis()).toUpperCase();
                    _resultMap.put("rd3Session",rd3Session);
                }
                return _resultMap;
            }
        }
        return ResultUtil.ERROR("数据验证错误，登录失败");
    }

    /**
     * 小程序通过页面路径得到小程序码
     * @param uriPath 页面路径
     * @return Map<String, Object>
     */
    @RequestMapping("/getQrcode")
    public Map<String, Object> getQrcode(@RequestParam("path") String uriPath){
        StopWatch stopWatch = new StopWatch();
        RestTemplate rest = new RestTemplate();
        String path = null;
        try{
            stopWatch.start("开始请求");//监控请求时间开始
            Map<String,String> configMap = sysConfigService.getSysConfigContext (ConfigName.WEIXINAPP);
            String appId = configMap.get("appId");
            String secret = configMap.get("secret");
            String token = WXLoginUtils.getMiniAccessToken(appId,secret,customCacheChannel);
            String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token="+ token;
            Map<String, Object> param = new HashMap<>();
            param.put("path", uriPath);
            param.put("width", 430);
            param.put("auto_color", false);

            Map<String,Object> line_color = new HashMap<>();
            line_color.put("r", 40);
            line_color.put("g", 103);
            line_color.put("b", 248);
            param.put("line_color", line_color);

            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            HttpEntity requestEntity = new HttpEntity(param, headers);
            ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class);
            logger.info("调用小程序生成微信小程序码URL接口返回结果：" + entity.getBody());
            stopWatch.stop();//监控请求时间结束

            stopWatch.start("生成小程序码");//监控请求时间开始
            byte[] result = entity.getBody();
            Map<String, byte[]> map = new HashMap<>();
            map.put("jpg", result);
            List<Map<String, byte[]>> list = new ArrayList<>();
            list.add(map);
            Map<String, Object> resultMap = fileUploadService.updateByteFileData(list,"qrcode");
            if (ObjectUtils.isEmpty(resultMap) || !ResultUtil.getSuccess(resultMap)) {
                return ResultUtil.ERROR("小程序码生成失败");
            }
            stopWatch.stop();//监控请求时间开始
            logger.info(stopWatch.prettyPrint());
            logger.info("获取总时间:"+stopWatch.getTotalTimeMillis());
            logger.info("---"+stopWatch.getLastTaskName());
            logger.info("---"+stopWatch.getLastTaskInfo());
            logger.info("---"+stopWatch.getTaskCount());

            return resultMap;
        }catch (Exception e){
            e.printStackTrace();
        }
        return ResultUtil.ERROR("系统繁忙，请稍后重试");
    }
}
